package gemsa.modeles;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.sql.DataSource;

import java.util.ArrayList;
import java.util.List;

import gemsa.beans.Reponse;
import gemsa.beans.Question;
import gemsa.outils.GestionBaseDeDonnees;
import gemsa.modeles.ModeleReponse;


/**
 * Classe ModeleReponse
 * @author Projet Dev Groupe 33
 * @version 1.0 Finale
 */
 
public class ModeleReponse 
{
	// Variables
	DataSource datasource=null;
	Connection connexion=null;
	ResultSet resultat=null;
	
	// Variables de pagination
	private int maxParPage;
	private int pageActuel;
	private int totalElement;
	
	// Constructeur par défaut
	public ModeleReponse(DataSource datasource)
	{		
		this.datasource=datasource;
	}
	
	// Accesseurs
	public int getMaxParPage() 
	{
		return maxParPage;
	}

	public int getPageActuel() 
	{
		return pageActuel;
	}

	public int getTotalElement() 
	{
		return totalElement;
	}

	
	// R�cup�rer la liste des reponses
	public List<Reponse> listerReponse(int idQuestion, int maxParPage, int pageActuel)
	{	
		// Variables
		PreparedStatement requete=null;
		Reponse reponse=null;
		String requeteString=null;
		List<Reponse> listeReponse=new ArrayList<Reponse>();
		int position=0;
	
		try
		{			
			// Ouverture d'une connexion
			connexion = datasource.getConnection();
		
			// Premi�re requ�te : on r�cup�re le nombre total de reponses
			
			// On cr�� la requ�te
			requeteString="SELECT COUNT(DISTINCT(reponse.id_reponse)) as total FROM reponse WHERE etatreponse=1";

			// Si il s'agit d'un listing de reponses en fonction de la question, on modifie la requ�te en cons�quence
			if(idQuestion!=0)
			{
				requeteString+=" AND id_question=?";
				
				// On pr�pare la requ�te
				requete=connexion.prepareStatement(requeteString);
				requete.setInt(1,idQuestion);
			}
			// Dans le cas contraire on liste toutes les reponses
			else
			{
				// On pr�pare la requ�te
				requete=connexion.prepareStatement(requeteString);
			}
			
			// Execution de la requ�te
			resultat=requete.executeQuery();
			
			// On r�cup�re le nombre de reponses
			if(resultat!=null)
			{
				if(resultat.next())
				{
					this.totalElement=resultat.getInt("total");
				}
			}
			
			// On v�rifie que la page demand�e est valable
			position=maxParPage*(pageActuel-1);
			if(position>totalElement || maxParPage>totalElement)
			{
				pageActuel=1;
			}
			
			// On d�finit les variables de pagination finales
			position=maxParPage*(pageActuel-1);
			this.maxParPage=maxParPage;
			this.pageActuel=pageActuel;
			
			// Deuxi�me requ�te : on r�cup�re la liste suivant une pagination
			requeteString="SELECT * FROM reponse WHERE etatreponse=1";

			// Si il s'agit d'un listing de reponses en fonction de l'question, on modifie la requ�te en cons�quence
			if(idQuestion!=0)
			{
				requeteString+=" AND id_question=?";
				requeteString+=" LIMIT " + position + "," + maxParPage;
				
				// On pr�pare la requ�te
				requete=connexion.prepareStatement(requeteString);
				requete.setInt(1, idQuestion);
			}
			// Dans le cas contraire on liste tous les reponses
			else
			{
				requeteString+=" LIMIT " + position + "," + maxParPage;
				
				// On pr�pare la requ�te
				requete=connexion.prepareStatement(requeteString);
			}
	
			// Execution de la requ�te
			resultat=requete.executeQuery();

			// On stocke le resultat une la liste de reponses
			if(resultat!=null)
			{
				while(resultat.next())
				{
					// On effectue le mappage des attributs avec les champs de la table SQL
					reponse=reponseAttributsMapper(resultat);
					
					// Ajoute l'objet a la liste de reponses
					listeReponse.add((Reponse)reponse);
				}
			}
		}
		catch(Exception e)
		{
			System.out.println(e);
			System.out.println("Erreur dans la requete dans la classe ModeleReponse fonction listeReponse");
		}
		
		finally
		{
			try
			{
				// Fermeture de la connexion
				if(resultat!=null)
				{
					GestionBaseDeDonnees.closeResulset(resultat);
				}
				if(requete!=null)
				{
					GestionBaseDeDonnees.closeRequest(requete);
				}
				if(connexion!=null)
				{
					GestionBaseDeDonnees.closeConnection(connexion);
				}
			}
			catch(Exception ex)
			{
				System.out.println("Erreur lors de la fermeture de la connexion avec la base de donn�es dans la classe ModeleReponse fonction listerReponse");
			}	
		}
		
		// Retourner la liste des reponses
		return listeReponse;
	}

	
	// R�cup�rer une reponse
	public Reponse getReponse(int idReponse)
	{	
		// Variables
		PreparedStatement requete=null;
		Reponse reponse=null;
		String requeteString=null;
	
		try
		{			
			// Ouverture d'une connexion
			connexion=datasource.getConnection();
			
			// Cr�ation de la requ�te
			requeteString="SELECT * FROM reponse WHERE id_reponse=?";
			
			// On pr�pare la requ�te
			requete=connexion.prepareStatement(requeteString);
			requete.setInt(1,idReponse);
				
			// Execution de la requ�te
			resultat=requete.executeQuery();

			// On stocke le resultat dans l'objet reponse
			if(resultat!=null)
			{
				if(resultat.next())
				{
					// On effectue le mapping des attributs avec les champs de la table SQL
					reponse=reponseAttributsMapper(resultat);
				}
			}
		}
		catch(Exception e)
		{
			// L'id de la reponse n'exite pas, on initialise la reponse � null
			reponse=null;
			System.out.println("Erreur dans la requete dans la classe ModeleReponse fonction getReponse");
		}
		finally
		{
			try
			{
				// Fermeture de la connexion
				if(resultat!=null)
				{
					GestionBaseDeDonnees.closeResulset(resultat);
				}
				if(requete!=null)
				{
					GestionBaseDeDonnees.closeRequest(requete);
				}
				if(connexion!=null)
				{
					GestionBaseDeDonnees.closeConnection(connexion);
				}
			}
			catch(Exception ex)
			{
				System.out.println("Erreur lors de la fermeture de la connexion avec la base de donn�es dans la classe ModeleReponse fonction getReponse");
			}	
		}
		
		// Retourner la reponse
		return reponse;
	}
	
	
	
	
	/* =========================================
	 * Partie Admin
	 * =========================================
	 */
	
	// Retourner la liste des reponses
	public List<Reponse> listeReponseAdmin(int maxParPage, int pageActuel)
	{	
		// Variables
		PreparedStatement requete=null;
		Reponse reponse=null;
		String requeteString=null;
		List<Reponse> listeReponse=new ArrayList<Reponse>();
		int position=0;
	
		try
		{			
			// Ouverture d'une connexion
			connexion=datasource.getConnection();
			
			// Premi�re requ�te : on r�cup�re le nombre total de reponses
			requeteString="SELECT COUNT(DISTINCT(reponse.id_reponse)) as total FROM reponse WHERE 1";

			// Pr�paration de la requ�te
			requete=connexion.prepareStatement(requeteString);
			
			// Execution de la requ�te
			resultat=requete.executeQuery();
			
			// On r�cup�re le nombre de reponses
			if(resultat!=null)
			{
				if(resultat.next())
				{
					this.totalElement=resultat.getInt("total");
				}
			}
			// On v�rifie que la page demand�e est valable
			position=maxParPage*(pageActuel-1);
			if(position>totalElement || maxParPage>totalElement)
			{
				pageActuel=1;
			}
			
			// On d�finit les variables de pagination finale
			position=maxParPage*(pageActuel-1);
			this.maxParPage=maxParPage;
			this.pageActuel=pageActuel;
		
			// Deuxi�me requ�te : on r�cup�re la liste suivant une pagination
			requeteString="SELECT * FROM reponse WHERE 1";
			requeteString+=" LIMIT " + position + "," + maxParPage;
			
			// Pr�paration de la requ�te
			requete=connexion.prepareStatement(requeteString);
			
			// Execution de la requ�te
			resultat=requete.executeQuery();

			// On stocke le resultat dans une liste
			if(resultat!=null)
			{
				while(resultat.next())
				{
					// On effectue le mapping des attributs avec les champs de la table SQL
					reponse=reponseAttributsMapper(resultat);
					
					// Ajoute l'objet a la liste d'reponses
					listeReponse.add((Reponse)reponse);
				}
			}
		}
		catch(Exception e)
		{
			System.out.println("Erreur dans la requete dans la classe ModeleReponse fonction ListeReponseAdmin");
		}
		finally
		{
			try
			{
				// Fermeture de la connexion
				if(resultat!=null)
				{
					GestionBaseDeDonnees.closeResulset(resultat);
				}
				if(requete!=null)
				{
					GestionBaseDeDonnees.closeRequest(requete);
				}
				if(connexion!=null)
				{
					GestionBaseDeDonnees.closeConnection(connexion);
				}
			}
			catch(Exception ex)
			{
				System.out.println("Erreur lors de la fermeture de la connexion avec la base de donn�es dans la classe ModeleReponse fonction ListeReponseAdmin");
			}	
		}
		
		// Retourner la liste des reponses
		return listeReponse;
	}
	
	
	
	// Ajouter une reponse
	public int ajouterReponse(Reponse reponse)
	{	
		// Variables
		PreparedStatement requete=null;
		String requeteString=null;
		int codeErreur=0;
	
		try
		{			
			// Ouverture d'une connexion
			connexion=datasource.getConnection();
			
			// Cr�ation de la requ�te
			requeteString="INSERT INTO reponse (nomreponse, descriptionreponse, coefficientreponse, etatreponse, id_question) VALUES(?,?,?,?,?)";
			
			// Pr�paration de la requ�te
			requete=connexion.prepareStatement(requeteString);
			requete.setString(1, reponse.getNom());
			requete.setString(2, reponse.getDescription());
			requete.setDouble(3,reponse.getCoefficient());
			requete.setInt(4, reponse.getEtat());
			requete.setInt(5, reponse.getQuestion().getId());

			// On vide la reponse par s�curit�
			reponse = null;
			
			// Execution de la requ�te
			codeErreur=requete.executeUpdate();
		}
		catch(Exception e)
		{
			codeErreur=0;
			System.out.println("Erreur dans la requete dans la classe ModeleReponse fonction ajouterReponse");
		}
		finally
		{
			try
			{
				// Fermeture de la connexion
				if(resultat!=null)
				{
					GestionBaseDeDonnees.closeResulset(resultat);
				}
				if(requete!=null)
				{
					GestionBaseDeDonnees.closeRequest(requete);
				}
				if(connexion!=null)
				{
					GestionBaseDeDonnees.closeConnection(connexion);
				}
			}
			catch(Exception ex)
			{
				System.out.println("Erreur lors de la fermeture de la connexion avec la base de donn�es dans la classe ModeleReponse fonction ajouterReponse");
			}	
		}
		
		// Retourner le code d'erreur
		return codeErreur;
	}
	
	
	
	// Supprimer une reponse
	public int supprimerReponse(int idReponse)
	{	
		// Variables
		PreparedStatement requete=null;
		ModeleNote modeleNote=null;
		String requeteString=null;
		int codeErreur=0;
	
		try
		{	
			// Initialisation du mod�le note
			modeleNote=new ModeleNote(this.datasource);
			
			// Ouverture d'une connexion
			connexion=datasource.getConnection();
			
			// Annulation de l'autocommit
			connexion.setAutoCommit(false);
			
			// Premi�re requ�te : suppression de la reponse
			requeteString="DELETE FROM reponse WHERE id_reponse = ?";
			
			// Pr�paration de la requ�te
			requete=connexion.prepareStatement(requeteString);
			requete.setInt(1, idReponse);
			
			// Execution de la requ�te
			codeErreur=requete.executeUpdate();
			
			// Si il n'y a pas eu d'erreur durant la suppression de la reponse, supprimer les notes de la reponse associ�e.
			if(codeErreur==1)
			{
				// Deuxi�me requ�te : suppression des notes de la reponse
				codeErreur=modeleNote.supprimerNote(idReponse);
			}
			// Si il n'y a pas eu d'erreur durant la suppression des notes des reponses, ou de la reponse elle-m�me : on fait un commit, sinon un rollback
			if(codeErreur==1)
			{
				GestionBaseDeDonnees.commit(connexion);
			}
			else
			{
				GestionBaseDeDonnees.rollback(connexion);
			}
		}
		catch(Exception e)
		{
			codeErreur=0;
			GestionBaseDeDonnees.rollback(connexion);
			System.out.println("Erreur dans la requete dans la classe ModeleReponse fonction supprimerReponse");
		}
		finally
		{
			try
			{
				// Fermeture de la connexion
				if(resultat!=null)
				{
					GestionBaseDeDonnees.closeResulset(resultat);
				}
				if(requete!=null)
				{
					GestionBaseDeDonnees.closeRequest(requete);
				}
				if(connexion!=null)
				{
					GestionBaseDeDonnees.closeConnection(connexion);
				}
			}
			catch(Exception ex)
			{
				System.out.println("Erreur lors de la fermeture de la connexion avec la base de donn�es dans la classe ModeleReponse fonction supprimerReponse");
			}	
		}
		
		// Retourner le code d'erreur
		return codeErreur;
	}
	
	
	
	
	// Modifier une reponse
	public int modifierReponse(Reponse reponse)
	{	
		// Variables
		PreparedStatement requete=null;
		String requeteString=null;
		int codeErreur=0;
	
		try
		{			
			// Ouverture d'une connexion
			connexion=datasource.getConnection();
			
			// Cr�ation de la requ�te
			requeteString="UPDATE reponse set nomreponse = ?, descriptionreponse = ?, coefficientreponse = ?, etatreponse = ?, id_question = ? WHERE id_reponse = ?";
			requete=connexion.prepareStatement(requeteString);
			requete.setString(1, reponse.getNom());
			requete.setString(2, reponse.getDescription());
			requete.setDouble(3,reponse.getCoefficient());
			requete.setInt(4, reponse.getEtat());
			requete.setInt(5, reponse.getQuestion().getId());
			requete.setInt(6, reponse.getId());
			
			// On vide la reponse par s�curit�
			reponse=null;
			
			// Execution de la requ�te
			codeErreur=requete.executeUpdate();
		}
		catch(Exception e)
		{
			System.out.println("Erreur dans la requete dans la classe ModeleReponse fonction modifierReponse");
		}
		finally
		{
			try
			{
				// Fermeture de la connexion
				if(resultat!=null)
				{
					GestionBaseDeDonnees.closeResulset(resultat);
				}
				if(requete!=null)
				{
					GestionBaseDeDonnees.closeRequest(requete);
				}
				if(connexion!=null)
				{
					GestionBaseDeDonnees.closeConnection(connexion);
				}
			}
			catch(Exception ex)
			{
				System.out.println("Erreur lors de la fermeture de la connexion avec la base de donn�es dans la classe ModeleReponse fonction modifierReponse");
			}	
		}
		
		// Retourner le code d'erreur
		return codeErreur;
	}
	
	
	
	// R�aliser la transformation Relationnel vers Objet
	public Reponse reponseAttributsMapper(ResultSet resultat)
	{
		// Variables
		Reponse reponse=null;
		ModeleQuestion modeleQuestion=null;
		ModeleNote modeleNote=null;
		
		// Initialisation des modèles
		modeleQuestion=new ModeleQuestion(this.datasource);
		modeleNote=new ModeleNote(this.datasource);
		
		// Initalisation de l'objet reponse
		reponse=new Reponse();
		
		try
		{	
			// On renseigne l'objet reponse
			if(resultat.getString("id_reponse")==null)
			{
				reponse.setId(0);
			}
			else
			{
				reponse.setId(resultat.getInt("id_reponse"));
			}
			
			if(resultat.getString("nomreponse")==null)
			{
				reponse.setNom("");
			}
			else
			{
				reponse.setNom(resultat.getString("nomreponse"));
			}
			
			if(resultat.getString("descriptionreponse")==null)
			{
				reponse.setDescription("");
			}
			else
			{
				reponse.setDescription(resultat.getString("descriptionreponse"));
			}
		
			if(resultat.getString("coefficientreponse")==null)
			{
				reponse.setCoefficient(0.0);
			}
			else
			{
				reponse.setCoefficient((resultat.getDouble("coefficientreponse")));
			}
			
			if(resultat.getString("etatreponse")==null)
			{
				
				reponse.setEtat(0);
			}
			else
			{
				reponse.setEtat(resultat.getInt("etatreponse"));
			}
			
			if(resultat.getString("id_question")==null)
			{
				reponse.setQuestion(new Question());
			}
			else
			{
				reponse.setQuestion(modeleQuestion.getQuestion(resultat.getInt("id_question")));
			}
			
			// On récupère la note de la reponse
			reponse.setNote(modeleNote.getNoteReponse(reponse.getId()));
		}
		catch (Exception e) 
		{
			// Si il y a une erreur durant le mapping des attributs avec la base on renvoi un objet null
			reponse=null;
			System.out.println("Erreur lors du mappage des attributs d'une reponses dans la classe ModeleReponse fonction ReponseAttributsMapper");
		}
		
		// On retourne la reponse
		return reponse;
	}
	
	
}
